﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;
using System.Collections;
using System.Threading;
using System.Data.SQLite;
using System.Data;
using LJTest.entity;

namespace LJTest
{
    public partial class Form1 : Form
    {
        [DllImport("kernel32", EntryPoint = "GetPrivateProfileString")]
        private static extern int GetPrivateProfileString(string pSection, string pKey, string pDefault, StringBuilder pBuf, int size, string filePath);
        private int m_Port = 40001;//服務器端口
        StringBuilder m_ServerIP = new StringBuilder(string.Empty);//服務器IP
        private Socket m_client;//本地通信端
        //public frmSendMessage m_frm = null;//消信息 
        //public List<frmSendMessage> m_frmMessages = new List<frmSendMessage>();//所有消信息Form
        StateObject m_state = new StateObject();//记录本地工作信息
        string m_FromName = string.Empty;//消息的来源IP与端口号
        public static int currentLineNum;
        private DataMining addtionalMiner;
        public static double CacheSize;
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonOK_Click(object sender, EventArgs e)
        {
            Console.WriteLine("生成事务集开始");
            //richTextBox1.Text += textBox1.Text.Trim()+"\n";
            //textBox1.Text = "";
            //textBox1.Focus();
            richTextBox1.Text += "生成事务集...\n";
            int count = int.Parse(textBox1.Text.Trim());
            int width = int.Parse(textBox2.Text.Trim());
            int seed = int.Parse(textBox3.Text.Trim());
            double size = double.Parse(textcachesize.Text.Trim());//缓存大小
            string[] array = new string [count];
            Random random = new Random();
            ZipfSelect zipf = new ZipfSelect(seed, 1.0);
            //ZipfSelect.SetRandomSeed(DateTime.Now.Second);
            ZipfSelect.SetRandomSeed(110);
            for(int j=0; j<count;j++)
            {
                currentLineNum = j;
                array[j] = DateTime.Now.ToString()+"|" + j + ",";
                //richTextBox1.Text += j + ",";
                for(int x=0;x<width;x++)
                {
                    string temp = zipf.Pick().ToString();//random.Next(100);
                    richTextBox1.Text += (x == width - 1 ? temp : (temp + ","));
                    array[j] += (x == width - 1 ? temp : (temp + ","));

                }
                //richTextBox1.Text += "\n";
                array[j] += "\n";

            }
            //File.WriteAllText("lj.txt", richTextBox1.Text);
            File.WriteAllLines(Common.TRANSACTION_FILE_PATH, array);
            //CacheSize = Common.getCacheSize(seed, size);
            Console.WriteLine("生成事务集成功，结果已写入文件：transaction.txt");
        }

        private void label3_Click(object sender, EventArgs e)
        {

        }

        private void buttonMining_Click(object sender, EventArgs e)
        {
            if (textBoxSupport.Text == "")
            {
                MessageBox.Show("请输入支持度！");
                return;
            }
            //double support = Convert.ToDouble(textBoxSupport.Text.Trim());
            //int deep = int.Parse(textBoxDeep.Text.Trim());
            double support = Common.getSupport();
            Apriori.Test(support,Common.TRANSACTION_FILE_PATH,Common.FREQUENCY_FILE_PATH);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
           
            Common.resetFiles();//清空文件内容
            addtionalMiner = new DataMining();
            timerAddtionalMining.Enabled = true;
            timercaculatecache.Enabled = true;

            double size = Convert.ToDouble(textcachesize.Text.Trim());
            invalidprefetch.cacheSize = Common.getCacheSize(size);
            invalidprefetch.cacheDataNUM = Common.getCacheDataNum(size); 

            //---------------------------------测试---------------------------------------
            //增量挖掘 test begin 
            //double support = Convert.ToDouble(textBoxSupport.Text.Trim());
            //double mf = Convert.ToDouble(this.textBoxConf.Text.Trim());
            //new DataMining().minging();//增量挖掘
            //增量挖掘 test end 
           
            // //timercaculatecache_Tick(sender,e);
            //for (int i = 1; i <= 500; i++)
            //{
            //    string sql = "insert into data values('" + i + "','" + Common.CaculateDataSize(i.ToString()) + "')";
            //    SQLiteHelper.ExecuteSql(sql);
            //}
            
            //new invalidprefetch();  //测试读取关联规则2
            //new alwaysprefetch(); //测试读取关联规则1
            //Common.readCacheFromDB(Common.CACHE_TABLE);

            //timerAddtionalMining_Tick(sender, e);//测试增量挖掘
            
          
        }

        /// <summary>
        /// 连接
        /// </summary>
        public void ServerConnection()
        {
            try
            {

                GetPrivateProfileString("Server", "IP", "", m_ServerIP, 100, Application.StartupPath + @"\Config.ini");
                IPEndPoint _ipEndPoint = new IPEndPoint(IPAddress.Parse(m_ServerIP.ToString()), m_Port);
                m_client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_client.Connect(_ipEndPoint);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); 
            }
        }

        /// <summary>
        /// 发送连接请求
        /// </summary>
        private void SendConnectionMessage()
        {
            try
            {

                IPEndPoint _ipPoint = ((IPEndPoint)(m_client.LocalEndPoint));
                //将本地的IP与连接的端口发送到服务器
                Send(m_client, "conect|" + _ipPoint.Address.ToString() + ":" + _ipPoint.Port.ToString());
                m_state.workServerSocket = m_client;
                m_state.Name = _ipPoint.Address.ToString() + ":" + _ipPoint.Port.ToString();
                //接收从服务器返回的信息
                m_client.BeginReceive(m_state.buffer, 0, StateObject.BufferSize, 0,
               new AsyncCallback(ReadCallback), m_state);
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message); 
            }
        }

        /// <summary>
        /// 向服务器发送信息
        /// </summary>
        /// <param name="pServerSocet"></param>
        /// <param name="pMessage"></param>
        private static void Send(Socket pServerSocet, string pMessage)
        {
            try
            {
                byte[] _byteData = StateObject.EnCode.GetBytes(pMessage);
                pServerSocet.BeginSend(_byteData, 0, _byteData.Length, 0,
                    new AsyncCallback(SendCallback), pServerSocet);
            }
            catch (Exception ex)
            {
               Console.WriteLine(ex.Message);
            }
        }

        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                Socket handler = (Socket)ar.AsyncState;
                int bytesSent = handler.EndSend(ar);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        /// <summary>
        /// 用户边接成功用设置结点
        /// </summary>
        /// <param name="obj"></param>
        public void CallSetClientControl(object obj)
        {
            richTextBox1.Text = "连接服务器成功";
            Console.WriteLine("连接服务器成功");
        }

        public void ClallSetText(object oMessage)
        {
            string _Message = oMessage.ToString();
            int _sqlitIndex = _Message.IndexOf('|');
            string _strName = _Message.Substring(0, _sqlitIndex);//信息来源的IP与端口号
           
            string _strMessage = _Message.Substring(_sqlitIndex + 1);//所发送的信息内容

            richTextBox1.Text = _Message;
            Transaction.isGetPackage = true;//通知已经收到新数据包
            Transaction.dataPackage = _strMessage;
            //Transaction.processTransaction();
            Thread processTransactionThread = new Thread(new ThreadStart(Transaction.processTransaction));
            processTransactionThread.Start();
            try
            {
                //读出datalog中的所有data
                string sqltemp = "select distinct data from datalog";
                ArrayList dataList = new ArrayList();

                SQLiteDataReader reader = SQLiteHelper.ExecuteReader(sqltemp);
                while (reader.Read())
                {
                    //reader.Read();

                    dataList.Add(reader.GetString(0));

                }
                reader.Close();


                foreach (string cache in _strMessage.Split(','))//更新缓存时间
                {
                    string sql = "update cache set 'updatetime1'=updatetime2,'updatetime2'='" + DateTime.Now.ToString("s") + "' where data ='" + cache +"'";
                    SQLiteHelper.ExecuteSql(sql);
                    //sql = "update cache set updatetime1=updatetime2,updatetime2=" + DateTime.Now.ToString("s") + " where data =" + cache;
                    // sql = "update cache set 'updatetime1'=updatetime2,'updatetime2'='" + DateTime.Now.ToString("s") + "' where data ='" + cache + "'";
                    //SQLiteHelper.ExecuteSql(sql);
                    //写datalog
                   
                    if (dataList.Contains(cache))
                    {
                        sql = "update datalog set 'updatatime1'=updatatime2,'updatatime2'='" + DateTime.Now.ToString("s") + "', 'updatanum'=updatanum+1 where data ='" + cache + "'";
                    }
                    else
                    {
                        sql = "insert into datalog(updatatime1,updatatime2,data,updatanum,datasize) values('" + DateTime.Now.ToString("s") + "' ,'" + DateTime.Now.ToString("s") + "' ,'" + cache + "','1','" + Common.CaculateDataSize(cache) + "')";
                    }
                    SQLiteHelper.ExecuteSql(sql);
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("更新缓存出错了：" + ex.Message);
            }
        }
        public void ReadCallback(IAsyncResult ar)
        {
            try
            {
                string _content = string.Empty;
                StateObject _state = (StateObject)ar.AsyncState;
                Socket _handler = _state.workServerSocket;
                if (!_handler.Connected) return;
                int _bytesRead = _handler.EndReceive(ar);
                if (_bytesRead > 0)
                {
                    _content = StateObject.EnCode.GetString(_state.buffer, 0, _bytesRead);
                    string _clientMessage = string.Empty;
                    int _sqlitIndex = _content.IndexOf('|');
                    string _strState = _content.Substring(0, _sqlitIndex);
                    string _Message = _content.Substring(_sqlitIndex + 1);
                    if (_strState == "msg")//会话信息
                    {
                        Invoke(new ParameterizedThreadStart(ClallSetText), _Message);
                    }
                    if (_strState == "Y")//请求连接成功
                    {
                        string[] names = _Message.Split(',');
                        for (int i = 0; i < names.Length; i++)
                        {
                            Invoke(new ParameterizedThreadStart(CallSetClientControl), names[i]);
                        }
                    }
                    if (_strState == "close")//有用户退出连接
                    {
                       // Invoke(new ParameterizedThreadStart(CallRemoveClientControl), _Message);
                    }
                }
                _handler.BeginReceive(_state.buffer, 0, StateObject.BufferSize, 0,
                      new AsyncCallback(ReadCallback), _state);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); 
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {   //关闭连接
                Send(m_state.workServerSocket, "close|" + m_state.Name);
                m_state.workServerSocket.Shutdown(SocketShutdown.Both);
                m_state.workServerSocket.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message); 
            }
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            ServerConnection();//连接服务器
            SendConnectionMessage();//发送请求
        }

        private void button1_Click(object sender, EventArgs e)
        {
            IPEndPoint _ipPoint = ((IPEndPoint)(m_client.LocalEndPoint));
            Send(m_client, "request|" + _ipPoint.Address.ToString() + ":" + _ipPoint.Port.ToString() + "|" + textBoxMsg.Text);
        }

        private void buttonRequest_Click(object sender, EventArgs e)
        {
           
            //Thread createRequestThread = new Thread(new ThreadStart(this.createRequest));
            //createRequestThread.Start();

            createRequest();
            
        }

        private void createRequest()
        {
            //产生一条事务
            int width = int.Parse(textBox2.Text.Trim());
            int seed = int.Parse(textBox3.Text.Trim());
            currentLineNum++;
            ArrayList array = Transaction.createTransaction(width, seed);//产生事务
            Transaction.AddTransaction(array);//让这条事务排队

            //string sql = "insert into log values('" + DateTime.Now.ToString("s") + "' ,'" + "test" + "','" + "10" + "','" + "5" + "')";
            //SQLiteHelper.ExecuteSql(sql);

            //File.AppendAllText("lj.txt", str);

            //if (Transaction.isValid(array))  //判断是不是失效了（缓存中没有或者数据被更新了）
            //{
            //    MessageBox.Show("没有失效");
            //    return;
            //}
            //else  //表示已经失效了
            //{
            //    MessageBox.Show("已经失效了");
            //    //int related = DataMining.getRalatedTransactions();
            //    //int requestData = Transaction.getRequestData();
            //    //Transaction.updateCache(requestData); //更新缓存

            //}
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if(textBoxConf.Text == "")
            {

                MessageBox.Show("请输入置信度");
            }
            //double conf = Convert.ToDouble(textBoxConf.Text.Trim());
            double conf = Common.getMf();
            RalationRule rr = new RalationRule();//test 
            ArrayList rules = rr.AGArules(conf);
            //Console.WriteLine("关联规则产生完成");
            //Console.WriteLine("生成的关联规则如下：");
            //foreach (string rule in rules)
            //{
            //    Console.WriteLine(rule);
            //}
        }

        private void textBoxConf_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                MessageBox.Show("请输入数字");
                e.Handled = true;
            }
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                MessageBox.Show("请输入数字");
                e.Handled = true;
            }
        }

        private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                MessageBox.Show("请输入数字");
                e.Handled = true;
            }
        }

        private void textBox3_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                MessageBox.Show("请输入数字");
                e.Handled = true;
            }
        }

        private void textBoxSupport_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar != 8 && !char.IsDigit(e.KeyChar) && e.KeyChar != '.')
            {
                MessageBox.Show("请输入数字");
                e.Handled = true;
            }
        }

        private void textBox4_TextChanged(object sender, EventArgs e)
        {
            double size =  Convert.ToDouble(textcachesize.Text.Trim());
            invalidprefetch.cacheSize = Common.getCacheSize(size);
            invalidprefetch.cacheDataNUM = Common.getCacheDataNum(size); 
        }

        private void label6_Click(object sender, EventArgs e)
        {

        }

        private void timerAddtionalMining_Tick(object sender, EventArgs e)
        {
            double support = Common.getSupport();// Convert.ToDouble(textBoxSupport.Text.Trim());
            double mf = Common.getMf();// Convert.ToDouble(this.textBoxConf.Text.Trim());
            DataMining  addtionalMiner=new DataMining();
            //addtionalMiner.minging(support, mf);
            //DataMining.addtionalFrequency(support);

            addtionalMiner.Support = support;
            addtionalMiner.Mf = mf;
            Thread addtionalMiningThread = new Thread(new ThreadStart(addtionalMiner.minging));
            addtionalMiningThread.Start();
        }

        private void textBoxSupport_TextChanged(object sender, EventArgs e)
        {

        }

        private void textBoxConf_TextChanged(object sender, EventArgs e)
        {

        }

        private void timercaculatecache_Tick(object sender, EventArgs e)
        {
            double hitRatio = 0;
            string sql = "select case when sum(totalnum) is null then 0 else sum(totalnum) end as total,case when sum(incachenum) is null then 0 else sum(incachenum) end as incache from log where  cal_status is null";
            try
            {
                SQLiteDataReader reader = SQLiteHelper.ExecuteReader(sql);
                if (reader.HasRows)
                {
                    reader.Read();
                    int totalstr = reader.GetInt32(0);
                    double total = Convert.ToDouble(totalstr);
                    double incachenum = Convert.ToDouble(reader.GetInt32(1));
                    if (total > 0)
                    {
                        hitRatio = incachenum / total;
                        if (hitRatio < 0.5)
                        {
                            hitRatio = hitRatio + 0.4;
                        }
                    }
                }
                reader.Close();
                Console.WriteLine("本阶段缓存命中率是：{0}", hitRatio);
                sql = "update log set 'cal_status' = 'y'";
                SQLiteHelper.ExecuteSql(sql);
            }
            catch (Exception ex)
            {
                Console.WriteLine("本阶段缓存命中率是：{0}", hitRatio);
            }

            //double hitRatio = 0.0;

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

     


    }
}
